module Common: sig
	val id: 'a -> 'a
	val dup: 'a -> 'a * 'a
	val some: 'a -> 'a option

	val curry2: ('a * 'b -> 'c) -> 'a -> 'b -> 'c
	val uncurry2: ('a -> 'b -> 'c) -> 'a * 'b -> 'c
	val curry3: (('a * 'b) * 'c -> 'd) -> 'a -> 'b -> 'c -> 'd
	val uncurry3: ('a -> 'b -> 'c -> 'd) -> ('a * 'b) * 'c -> 'd
	
	val first: 'a -> 'b -> 'a
	val second: 'a -> 'b -> 'b

	val ( =* ): 'a -> 'a -> bool
	val ( <>* ): 'a -> 'a -> bool
end

module Event: sig
	type +'a t

	val none: 'a t
	val tag: 'a -> 'b t -> 'a t
	val attach: 'a -> 'b t -> ('a * 'b) t
	val map: ('a -> 'b) -> 'a t -> 'b t
	val may: 'a option t -> 'a t
	val lmerge: 'a t -> 'a t -> 'a t
	val rmerge: 'a t -> 'a t -> 'a t
	val merge: ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t
	val map_merge: ('a -> 'c) -> ('b -> 'c) -> ('a -> 'b -> 'c) ->
		'a t -> 'b t -> 'c t
	val cat: 'a t list -> 'a list t
	val join: 'a t -> 'b t -> ('a * 'b) t
	val split: ('a * 'b) t -> 'a t * 'b t
	val filter: ('a -> bool) -> 'a t -> 'a t
	val map_filter: ('a -> 'b option) -> 'a t -> 'b t
	val get: 'a t -> 'b t -> 'a option t
	
	(* internal *)
	val return: 'a -> 'a t
	val map_default: 'b -> ('a -> 'b) -> 'a t -> 'b
	val is_event: 'a t -> bool
	val from_event: 'a t -> 'a
end

type (-'a, +'b) sf
exception Undefined_signal

val arr: ('a -> 'b) -> ('a, 'b) sf
val arr2: ('a -> 'b -> 'c) -> ('a * 'b, 'c) sf
val ( >>> ): ('a, 'b) sf -> ('b, 'c) sf -> ('a, 'c) sf
val ( <<< ): ('a, 'b) sf -> ('c, 'a) sf -> ('c, 'b) sf
val first: ('a, 'b) sf -> ('a * 'c, 'b * 'c) sf
val second: ('a, 'b) sf -> ('c * 'a, 'c * 'b) sf
val ( *** ): ('a, 'b) sf -> ('c, 'd) sf -> ('a * 'c, 'b * 'd) sf
val ( &&& ): ('a, 'b) sf -> ('a, 'c) sf -> ('a, 'b * 'c) sf
val returnA: ('a, 'a) sf
val loop: 'a -> ('b * 'a, 'c * 'a) sf -> ('b, 'c) sf
val loopq: 'a -> ('b * 'a, 'c * 'a) sf -> ('b, 'c) sf
val fix: ('a -> ('b, 'c) sf) -> (('b, 'c) sf -> 'a) -> 'a

val identity: ('a, 'a) sf
val constant: 'a -> ('b, 'a) sf

val never: ('a, 'b Event.t) sf
val now: 'b -> ('a, 'b Event.t) sf
val edge: 'a -> (bool, 'a Event.t) sf
val delta: ('a -> 'a -> 'b) -> ('a, 'b Event.t) sf
val changes: ('a, 'a Event.t) sf
val changesq: ('a, 'a Event.t) sf
val latch: ('a * 'b Event.t, 'a Event.t) sf
val once: ('a Event.t, 'a Event.t) sf
val take: int -> ('a Event.t, 'a Event.t) sf
val drop: int -> ('a Event.t, 'a Event.t) sf

val par: ('a, 'b) sf list -> ('a, 'b list) sf

val hold: 'a -> ('a Event.t, 'a) sf
val track: 'a -> ('a option, 'a) sf
val gate: ('a * 'b Event.t, 'a) sf

val accum: 'a -> (('a -> 'a) Event.t, 'a Event.t) sf
val collect: ('b -> 'a -> 'b) -> 'b -> ('a Event.t, 'b Event.t) sf

val switch: ('a, 'b) sf -> ('a, ('a, 'b) sf Event.t) sf -> ('a, 'b) sf
val rswitch: ('a, 'b) sf -> ('a * ('a, 'b) sf Event.t, 'b) sf
val dswitch: ('a, 'b Event.t) sf -> ('a, ('a, 'b Event.t) sf Event.t) sf ->
	('a, 'b Event.t) sf
val drswitch: ('a, 'b Event.t) sf ->
	('a * ('a, 'b Event.t) sf Event.t, 'b Event.t) sf
val srswitch: ('b -> 'c) -> ('c -> ('a, 'b) sf) -> 'c ->
	('a * ('c -> ('a, 'b) sf) Event.t, 'b) sf

val collapse: ('a, ('a, 'b) sf) sf -> ('a, 'b) sf
val rcollapse: ('a * ('a, 'b) sf, 'b) sf
val srcollapse: ('b -> 'c) -> 'c -> ('a * ('c -> ('a, 'b) sf), 'b) sf
val acollapse: ('c * ('a, 'b) sf) list -> ('a * 'c, 'b) sf

val reactimate: ('a, 'b) sf -> 'a -> ('a, 'b) sf * 'b

(* internal *)
val const_arr: ('a -> bool * 'b) -> ('a, 'b) sf
val is_constant: ('a, 'b) sf -> bool
